﻿// EasyTSharke.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <sstream>
#include <vector>
#include <fstream>
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"

using namespace std;


struct Packet {
    int frame_number;       // 数据包编号
    string time;            // 数据包时间戳
    uint32_t cap_len;            // 
    string src_ip;          // 源IP地址
    int src_port;           // 源端口
    string dst_ip;          // 目标IP地址
    int dst_port;           // 目标端口
    string protocol;        // 协议
    string info;            // 数据包概要信息
    uint32_t file_offset;
};

// Pcap全局文件头
struct PcapHeader
{
    uint32_t magic_number;
    uint16_t version_major;
    uint16_t version_minor;
    int32_t thiszone;
    uint32_t sigfigs;
    uint32_t snaplen;
    uint32_t network;
};

// 每个数据报文前面的头
struct PacketHeader
{
    uint32_t ts_sec;
    uint32_t ts_usec;
    uint32_t caplen;
    uint32_t len;
};

#ifdef _WIN32
#include <windows.h>
// UTF-8转ANSI
static std::string UTF8ToANSIString(const std::string& utf8Str) {
    // 获取UTF-8字符串的长度
    int utf8Length = static_cast<int>(utf8Str.length());

    // 将UTF-8转换为宽字符（UTF-16）
    int wideLength = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), utf8Length, nullptr, 0);
    std::wstring wideStr(wideLength, L'\0');
    MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), utf8Length, &wideStr[0], wideLength);

    // 将宽字符（UTF-16）转换为ANSI
    int ansiLength = WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), wideLength, nullptr, 0, nullptr, nullptr);
    std::string ansiStr(ansiLength, '\0');
    WideCharToMultiByte(CP_ACP, 0, wideStr.c_str(), wideLength, &ansiStr[0], ansiLength, nullptr, nullptr);

    return ansiStr;
}

#endif

void printPacket(const Packet& packet) {

    // 构建JSON对象
    rapidjson::Document pktObj;
    rapidjson::Document::AllocatorType& allocator = pktObj.GetAllocator();

    // 设置JSON为Object对象类型
    pktObj.SetObject();

    // 添加JSON字段
    pktObj.AddMember("frame_number", packet.frame_number, allocator);
    pktObj.AddMember("timestamp", rapidjson::Value(packet.time.c_str(), allocator), allocator);
    pktObj.AddMember("src_ip", rapidjson::Value(packet.src_ip.c_str(), allocator), allocator);
    pktObj.AddMember("dst_ip", rapidjson::Value(packet.dst_ip.c_str(), allocator), allocator);
    pktObj.AddMember("protocol", rapidjson::Value(packet.protocol.c_str(), allocator), allocator);
    pktObj.AddMember("info", rapidjson::Value(packet.info.c_str(), allocator), allocator);

    // 序列化为 JSON 字符串
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    pktObj.Accept(writer);

    // 打印JSON输出
    std::cout << buffer.GetString() << std::endl;
}


void parseLine(string line, Packet& packet)
{
    line = UTF8ToANSIString(line);

    if (line.back() == '\n') {
        line.pop_back();
    }

    stringstream ss(line);
    string field;
    vector<string> fields;

    while (std::getline(ss, field, '\t')) {  // 假设字段用 tab 分隔
        fields.push_back(field);
    }

    // 字段顺序：
    // 0: frame.number
    // 1: frame.time
    // 2: ip.src
    // 3: ipv6.src
    // 4: ip.dst
    // 5: ipv6.dst
    // 6: tcp.srcport
    // 7: udp.srcport
    // 8: tcp.dstport
    // 9: udp.dstport
    // 10: _ws.col.Protocol
    // 11: _ws.col.Info

    if (fields.size() >= 13) {
        packet.frame_number = std::stoi(fields[0]);
        packet.time = fields[1];
        packet.src_ip = fields[2].empty() ? fields[3] : fields[2];
        packet.dst_ip = fields[4].empty() ? fields[5] : fields[4];
        if (!fields[6].empty() || !fields[7].empty()) {
            packet.src_port = std::stoi(fields[6].empty() ? fields[7] : fields[6]);
        }

        if (!fields[8].empty() || !fields[9].empty()) {
            packet.dst_port = std::stoi(fields[8].empty() ? fields[9] : fields[8]);
        }
        packet.protocol = fields[10];
        packet.info = fields[11];
        packet.cap_len = std::stoi(fields[12]);
    }
}


void convertTojson(rapidjson::PrettyWriter<rapidjson::StringBuffer>& writer, Packet& packet)
{
    writer.StartObject();
    writer.Key("frameNum");
    writer.Int(packet.frame_number);
    writer.Key("timeStamp");
    writer.String(packet.time.c_str());
    writer.Key("src_ip");
    writer.String(packet.src_ip.c_str());
    writer.Key("src_port");
    writer.Int(packet.src_port);
    writer.Key("dst_ip");
    writer.String(packet.dst_ip.c_str());
    writer.Key("dst_port");
    writer.Int(packet.dst_port);
    writer.Key("protocol");
    writer.String(packet.protocol.c_str());
    writer.Key("info");
    writer.String(packet.info.c_str());
    writer.Key("file_offset");
    writer.Int(packet.file_offset);
    writer.Key("cap_len");
    writer.Int(packet.cap_len);
    writer.EndObject();
}

bool readPacketHex(const std::string& filePath, uint32_t offset, uint32_t length, std::vector<unsigned char>& buffer)
{
    std::ifstream file(filePath, std::ios::binary); //超出作用域自动析构关闭
    if (!file) {
        std::cerr << "无法打开文件！" << std::endl;
        return false;
    }

    file.seekg(offset, std::ios::beg);
    if (!file) 
        return false;
    buffer.resize(length);
    file.read(reinterpret_cast<char*>(buffer.data()), length);
    if (!file) {
        return false;
    }
    return true;
}

void printPacketHex(std::string filePath, Packet& p)
{
    std::vector<unsigned char> buffer;
    bool ret = readPacketHex(filePath, p.file_offset, p.cap_len, buffer);
    
    // 打印读取到的数据：
    printf("Packet Hex: ");
    if (ret)
    {
        for (unsigned char byte : buffer) {
            printf("%02X ", byte);
        }
    }
    printf("\n\n");
}


int main()
{
    // 1. 配置环境变量 文件放在程序同级目录
    //const char* command = R"(tshark -r packets.pcap -T fields -e frame.number -e frame.time -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport -e _ws.col.Protocol -e _ws.col.Info)";
    // 2. 在原始字面量里面，如果路径有空格""包裹，没有空格则不需要""包裹
    const char* command = R"("C:\Program Files\Wireshark\tshark.exe" -r H:\EasyTSharke\code\EasyTSharke\capture.pcap -T fields -e frame.number -e frame.time -e ip.src -e ipv6.src -e ip.dst -e ipv6.dst -e tcp.srcport -e udp.srcport -e tcp.dstport -e udp.dstport  -e _ws.col.Protocol -e _ws.col.Info -e frame.cap_len)";
    const char* filePath = R"(H:\EasyTSharke\code\EasyTSharke\capture.pcap)";
    cout << command << endl;
    FILE* pipe = _popen(command, "r");
    if (!pipe) {
        std::cerr << "Failed to run tshark command!"<< command << std::endl;
        return 1;
    }

    vector<Packet> packets;
    char buffer[1024];
    uint32_t file_offset = sizeof(PcapHeader);
    while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
        Packet packet;
        parseLine(buffer, packet);

        // 计算当前报文的偏移
        packet.file_offset = file_offset + sizeof(PacketHeader);
        // 更新偏移
        file_offset = file_offset + sizeof(PacketHeader) + packet.cap_len;

        packets.push_back(packet);
    }

    _pclose(pipe);
 
#if 1
    for (auto& p : packets)
    {
        printf("frame_number: %d  time: %s  src_ip: %s  dst_ip: %s  protocol: %s  info: %s\n",
            p.frame_number,
            p.time.c_str(),
            p.src_ip.c_str(),
            p.dst_ip.c_str(),
            p.protocol.c_str(),
            p.info.c_str());

        printPacketHex(filePath, p);
    }
    
#else

    rapidjson::StringBuffer s;
    rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(s);
    writer.StartArray();
    for (auto& packet : packets)
    {
        convertTojson(writer, packet);
        printPacketHex(filePath, packet);
    }

    writer.EndArray();

    std::cout << s.GetString() << std::endl;
#endif
    return 0;
}

